﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Drawing.Imaging;
using System.Net;
using System.Windows.Forms;
using System.Threading;
using mshtml;
using System.IO;
using System.Text.RegularExpressions;



namespace AllInOne.PrintUtils
{
    [System.Runtime.InteropServices.ComVisible(true)]
    public class PrintUtil
    {
        [DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool InternetSetCookie(string lpszUrlName, string lbszCookieName, string lpszCookieData);

        [DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool InternetGetCookie(string lpszUrlName, string lbszCookieName, StringBuilder lpszCookieData, ref int lpdwSize);

        [DllImport("kernel32.dll")]
        public static extern int GetLastError();

        [DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern bool InternetGetCookieEx(string pchURL, string pchCookieName, StringBuilder pchCookieData, ref uint pcchCookieData, int dwFlags, IntPtr lpReserved);



        private Action<string> alertCall;

        private string ipAddr = string.Empty;

        private Dictionary<string, string> hiddenInputs = new Dictionary<string, string>();

        private string checkUrl = "";

        private string respData = "";

        private bool nagigated = false;

        private CookieContainer cookies = null;

        private string strCookies = string.Empty;

        private CookieCollection cookieColl = null;

        private MyWebBrowser webBrowser = new MyWebBrowser();

        private bool isLogin = false;

        private HtmlDocument htmlDocument;

        private HtmlDocument webHtmlDocument;

        private string loginUser = string.Empty;

        private string loginPwd = string.Empty;

        private string[] validChar = new string[2];

        private string alertMsg = string.Empty;

        private string parseDom = string.Empty;

        private System.Threading.Timer tryTimer;

        private string[] reflushChar = new string[2];

        private string tryUrlFormat = "http://{0}/trffweb/ywsl.do?method=frd_ywsl&xtlb=02&cdbh=B101&cdbh=B101&xtlb=02";

        private Action<string, string> urledHandler;

        // private string printerCode = "VN39531445";

        public static string PRINTER_SN = "VN3Y536130";


        //private string printerCode = "";


        private WebBrowser wb = new WebBrowser();

        private object[] printPapgerLock = new object[0];

        public string printyear = string.Empty;

        private string loginIframeName = "ifrmaeecsideveh";


        public PrintUtil() {
            this.webBrowser.WBDocHostShowUIShowMessage += this.webBrowser_WBDocHostShowUIShowMessage;
            this.webBrowser.Navigated += this.webBrowser_Navigated;
            this.webBrowser.Navigating += this.webBrowser_Navigating;
            this.webBrowser.DocumentCompleted += this.webBrowser_DocumentCompleted;
            this.webBrowser.ScriptErrorsSuppressed = true;
            this.webBrowser.Visible = true;
            this.webBrowser.ObjectForScripting = this;

        }


        public void webBrowser_Navigating(object sender, WebBrowserNavigatingEventArgs e)
        {
            this.nagigated = false;
            System.Console.WriteLine("正在导航..." + e.Url);
        }


        public void webBrowser_Navigated(object sender, WebBrowserNavigatedEventArgs e)
        {
            try
            {
                IHTMLWindow2 ihtmlwindow = this.webBrowser.Document.Window.DomWindow as IHTMLWindow2;
                //string code = "window.alert = function(msg){window.external.myAlert(msg);};";
                //ihtmlwindow.execScript(code, "JScript");
            }
            catch (Exception value)
            {
                System.Console.Write(value);
            }
        }

        public void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            string absoluteUri = e.Url.AbsoluteUri;
            if (absoluteUri.Equals(this.checkUrl))
            {
                this.webHtmlDocument = this.webBrowser.Document;
                this.respData = this.webHtmlDocument.Body.OuterHtml;
                this.nagigated = true;
                System.Console.WriteLine("成功导航到指定Url");
                if (this.urledHandler != null)
                {
                    this.urledHandler(absoluteUri, this.respData);
                }
            }
        }

        public void webBrowser_WBDocHostShowUIShowMessage(object sender, ExtendedBrowserMessageEventArgs e)
        {
            e.Cancel = true;
            this.alertMsg = e.Text;
            System.Console.Write("捕获Alert弹框消息：" + this.alertMsg);
            SimpleConsole.WriteInfo("捕获Alert弹框消息：" + this.alertMsg, this);
            e.DlgResult = DialogResult.OK;
        }


        /// <summary>
        /// 打开登陆界面,并获取验证码图片
        /// </summary>
        /// <param name="ipaddr">服务器地址</param>
        /// <returns>图片</returns>
        public Image GetLoginVerifyCode(string ipaddr)
        {
            Image result;
            try
            {
                this.checkUrl = string.Format("http://{0}/trffweb/", this.ipAddr);
                this.ipAddr = ipaddr;
                this.webBrowser.Visible = true;
                this.webBrowser.ObjectForScripting = this;
                this.Execute(this.webBrowser, string.Format("http://{0}/trffweb/", this.ipAddr));
                this.htmlDocument = this.webBrowser.Document.Window.Document;
                string iframeName = "ifrmaeecsideveh";
                HtmlElement imageElement = this.webBrowser.Document.Window.Frames[iframeName].Document.All["image1"];
                Image webImage = this.GetWebImage(this.webBrowser,iframeName,imageElement);
                if (webImage == null)
                {
                    throw new Exception("获取验证吗图片失败");
                }
                result = webImage;
            }
            catch (Exception ex)
            {
                
                throw ex;
            }
            return result;
        }





        


        

        /// <summary>
        /// 获取网页中的图片
        /// </summary>
        /// <param name="webBrowser">浏览器</param>
        /// <param name="imageElement">图片元素</param>
        /// <returns>图片</returns>
        public Image GetWebImage(WebBrowser webBrowser, HtmlElement imageElement)
        {
            HTMLDocument document = (HTMLDocument)webBrowser.Document.DomDocument;
            HTMLBody body = (HTMLBody)document.body;
            IHTMLControlRange rang = (IHTMLControlRange)body.createControlRange();
            IHTMLControlElement Img = (IHTMLControlElement)imageElement.DomElement; //图片地址

            Image oldImage = Clipboard.GetImage();
            rang.add(Img);
            rang.execCommand("Copy", false, null);  //拷贝到内存
            Image numImage = Clipboard.GetImage();
            try
            {
                Clipboard.SetImage(oldImage);
            }
            catch
            {
            }

            return numImage;
        }


        /// <summary>
        /// 获取网页iframe中的图片
        /// </summary>
        /// <param name="webBrowser">浏览器</param>
        /// <param name="iframeName">iframe名字</param>
        /// <param name="imageElement">图片元素</param>
        /// <returns>图片</returns>
        public Image GetWebImage(WebBrowser webBrowser,string iframeName, HtmlElement imageElement)
        {
            HTMLDocument document = (HTMLDocument)webBrowser.Document.Window.Frames[iframeName].Document.DomDocument;
            HTMLBody body = (HTMLBody)document.body;
            IHTMLControlRange rang = (IHTMLControlRange)body.createControlRange();
            IHTMLControlElement Img = (IHTMLControlElement)imageElement.DomElement; //图片地址

            Image oldImage = Clipboard.GetImage();
            rang.add(Img);
            rang.execCommand("Copy", false, null);  //拷贝到内存
            Image numImage = Clipboard.GetImage();
            try
            {
                Clipboard.SetImage(oldImage);
            }
            catch
            {
            }

            return numImage;
        }

        /// <summary>
        /// 登陆
        /// </summary>
        /// <param name="verifyCode"></param>
        public void Login(string verifyCode,string yhdh,string mm) {
            try
            {
                foreach (HtmlElement element in this.webBrowser.Document.GetElementsByTagName("input"))
                {
                    string elementName = element.Name;
                    if (elementName == "yhdh") {
                        SimpleConsole.WriteInfo(string.Format("设置帐号：{0}",yhdh), this);
                        element.SetAttribute("value", yhdh);
                    }
                    if (elementName == "mm")
                    {
                        element.SetAttribute("value", mm);
                        SimpleConsole.WriteInfo(string.Format("设置帐号：{0}", mm), this);

                    }
                    if (elementName == "yzm")
                    {
                        element.SetAttribute("value", verifyCode);
                        SimpleConsole.WriteInfo(string.Format("验证码：{0}", verifyCode), this);

                    }

                }
                IHTMLDocument2 ihtmldocument = this.webBrowser.Document.Window.Document.DomDocument as IHTMLDocument2;
                IHTMLWindow2 parentWindow = ihtmldocument.parentWindow;
                Type type = parentWindow.GetType();
                type.InvokeMember("keylength", BindingFlags.GetProperty, null, parentWindow, new object[0]);
                type.InvokeMember("keylength", BindingFlags.SetProperty, null, parentWindow, new object[]
                {
                    "100"
                });
                this.strCookies = ihtmldocument.cookie;
                foreach (object obj2 in this.webBrowser.Document.Window.Document.GetElementsByTagName("input"))
                {
                    HtmlElement htmlElement = (HtmlElement)obj2;
                    if (htmlElement.Name == "Submit")
                    {
                        this.checkUrl = string.Format("http://{0}/trffweb/login.frm?method=check",this.ipAddr);
                        htmlElement.InvokeMember("click");
                        break;
                    }
                }
                PrintUtil.InternetSetCookie(string.Format("http://{0}/trffweb/vehprint.veh", this.ipAddr), "dyjbh", PRINTER_SN + ";expires = Sun,18-Jul-2021 00:00:00 GMT");
                PrintUtil.InternetSetCookie(string.Format("http://{0}/trffweb/vehprint.veh", this.ipAddr), "hgz", "1|175|1|175" + ";expires = Sun,18-Jul-2021 00:00:00 GMT");

                PrintUtil.InternetSetCookie(string.Format("http://{0}/trffweb/ywsl.do", this.ipAddr), "dyjxh", PRINTER_SN + ";expires = Sun,18-Jul-2021 00:00:00 GMT");

                this.cookieColl = new CookieCollection();
                this.cookies = new CookieContainer();
                this.AddCookie(this.cookieColl, this.strCookies, ihtmldocument.domain);
                this.cookies.Add(this.cookieColl);
            }
            catch (Exception ex)
            {
                throw ex;
            }
           
            System.Console.WriteLine(this.webBrowser.Document.DomDocument.ToString());
        }


        public bool CheckLogin()
        {

            SimpleConsole.WriteInfo(string.Format("checklogin"), this);

            bool result;
            lock (this.reflushChar)
            {
                HttpWebRequest httpWebRequest = null;
                HttpWebResponse httpWebResponse = null;
                try
                {
                    string checkUrl = string.Format("http://{0}/trffweb/ywsl.do?method=frd_ywsl&xtlb=02&cdbh=B101&cdbh=B101&xtlb=02", this.ipAddr);
                    ServicePointManager.DefaultConnectionLimit = 200;
                    httpWebRequest = (HttpWebRequest)WebRequest.Create(checkUrl);
                    httpWebRequest.Proxy = null;
                    httpWebRequest.CookieContainer = this.cookies;
                    httpWebRequest.Method = "POST";
                    httpWebRequest.Timeout = 10000;
                    httpWebRequest.ServicePoint.ConnectionLimit = 512;
                    httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
                    string responseText = string.Empty;
                    StreamReader streamReader = new StreamReader(httpWebResponse.GetResponseStream(), Encoding.GetEncoding("GBK"));
                    responseText = streamReader.ReadToEnd();
                    streamReader.Close();
                    httpWebRequest.Abort();
                    httpWebResponse.Close();
                    this.GetValidCode(responseText);
                    //SimpleConsole.WriteInfo(responseText, this);

                    bool loginFlag = responseText.Contains("档案编号") || responseText.Contains("查询部局限制人员信息表");
                    this.isLogin = loginFlag;
                    System.Console.WriteLine("刷新地址:" + checkUrl);
                    string value = loginFlag ? "已刷新：在线！" : "已刷新：掉线！";
                    SimpleConsole.WriteInfo(value,this);
                    result = this.isLogin;
                }
                catch (Exception ex)
                {
                    if (httpWebRequest != null)
                    {
                        httpWebRequest.Abort();
                    }
                    if (httpWebResponse != null)
                    {
                        httpWebResponse.Close();
                    }
                    SimpleConsole.WriteInfo(ex.StackTrace, this);
                    System.Console.WriteLine(ex);
                    result = false;
                }
            }
            return result;
        }



        public bool printing = false;


        public static bool printBackFlag = false;

        /// <summary>
        /// 根据证芯编号和流水号打印驾驶证
        /// </summary>
        /// <param name="zxbh">证芯编号</param>
        /// <param name="lsh">流水号</param>
        public bool PrintPaper(string zxbh, string lsh)
        {
            printing = false;
            SimpleConsole.WriteInfo(string.Format("开始打印驾驶证:证芯编号{0},流水号{1}", zxbh, lsh), this);
            string printPageUrl = string.Format("http://{0}/trffweb/ywsh.do?method=fr_print&lsh={1}&zjlb=1", this.ipAddr, lsh);
            SimpleConsole.WriteInfo(string.Format("printPageUrl:{0}", printPageUrl), this);

            this.webBrowser.Visible = true;
            this.webBrowser.ObjectForScripting = this;
            this.Execute(this.webBrowser, printPageUrl);

            PrintUtil.InternetSetCookie(printPageUrl, "dyjxh", PRINTER_SN + ";expires = Sun,18-Jul-2021 00:00:00 GMT");


            SimpleConsole.WriteInfo("设置打印机序号：" + PRINTER_SN, this);

            HtmlDocument document = this.webBrowser.Document.Window.Document;


            bool webLoaded = false;

            foreach (object obj in document.GetElementsByTagName("INPUT"))
            {
                HtmlElement htmlElement = (HtmlElement)obj;
                if (htmlElement.Name == "zxbh")
                {
                    SimpleConsole.WriteInfo("设置证芯编号：" + zxbh,this);
                    htmlElement.SetAttribute("value", zxbh);
                    webLoaded = true;
                    break;
                }
            }

            bool nextTdFlag = false;
            printBackFlag = false;
            foreach (object obj in document.GetElementsByTagName("TD"))
            {
                HtmlElement htmlElement = (HtmlElement)obj;
                if (htmlElement.InnerText!=null&&htmlElement.InnerText.IndexOf("副证提示")>-1)
                {
                    nextTdFlag = true;
                    continue;
                }
                if (nextTdFlag)
                {
                    string innerText = htmlElement.InnerText;
                    if (innerText!=null) 
                    {
                        SimpleConsole.WriteInfo("副证提示字节数:" + System.Text.Encoding.Default.GetByteCount(innerText) + "\n副证提示:" + innerText, this);
                        if (System.Text.Encoding.Default.GetByteCount(innerText) > 153)
                        {
                            printBackFlag = true;
                        }
                        else
                        {
                            printBackFlag = false;
                        }
                    }
                    break;
                }
            }


            if (!webLoaded)
            {
                return false;
            }

            HtmlDocument document2 = this.webBrowser.Document;
            //string outerHtml = document2.Body.OuterHtml;
            //string innerHtml = document2.Body.InnerHtml;
            //SimpleConsole.WriteInfo(outerHtml, this);
            //SimpleConsole.WriteInfo(innerHtml, this);
            SimpleConsole.WriteInfo("点击打印按钮", this);
            object obj2 = document2.InvokeScript("daying");
            return true;
        }

        /// <summary>
        /// 根据流水号打印合格标志
        /// </summary>
        /// <param name="lsh">流水号</param>
        public bool PrintLogo(string lsh) {
            string printPageUrl = string.Format("http://{0}/trffweb/vehprint.veh?method=forwardBusi&xtlb=01&gnid=0225&lsh={1}", this.ipAddr,lsh);
            this.webBrowser.Visible = true;
            this.webBrowser.ObjectForScripting = this;
            this.Execute(this.webBrowser, printPageUrl);

            bool webLoaded = false;

            //PrintUtil.InternetSetCookie(printPageUrl, "dyjxh", PRINTER_SN);
            HtmlDocument document = this.webBrowser.Document.Window.Document;
            foreach (object obj in document.GetElementsByTagName("INPUT"))
            {
                HtmlElement htmlElement = (HtmlElement)obj;
                if (htmlElement.GetAttribute("value") == "合格标志")
                {
                    webLoaded = true;
                    htmlElement.InvokeMember("click");
                    break;
                }
            }

            if (!webLoaded)
            {
                string outerHtml = document.Body.OuterHtml;
                SimpleConsole.WriteInfo(outerHtml, this);
            }
            return webLoaded;
        }

        public void DemoLost(string sfzmhm)
        {
            string busiPageUrl = string.Format("http://{0}/trffweb/ywsl.do?method=frd_ywsl&xtlb=02&cdbh=B101&cdbh=B101&xtlb=02", this.ipAddr);
            this.webBrowser.Visible = true;
            this.webBrowser.ObjectForScripting = this;
            this.Execute(this.webBrowser, busiPageUrl);
            HtmlDocument document = this.webBrowser.Document.Window.Document;

            foreach (HtmlElement selectElement in document.GetElementsByTagName("select"))
            {
                if (selectElement.Name == "gnid")
                {
                    selectElement.SetAttribute("value","0103");
                    document.InvokeScript("showGnid('0103')");
                    break;
                }
            }

            

            foreach (HtmlElement inputElement in document.GetElementsByTagName("input"))
            {
                if (inputElement.Name == "sfzmhm")
                {
                    inputElement.SetAttribute("value", sfzmhm);
                }
                if (inputElement.Name == "ywyy")
                {
                    string value = inputElement.GetAttribute("value");
                    string checkedFlag = inputElement.GetAttribute("checked");
                   
                    if (checkedFlag == "False" && (value == "E" || value == "F"))
                    {
                        inputElement.InvokeMember("click");
                    }
                }

            }
            this.checkUrl = string.Format("http://{0}/trffweb/ywsl.do?method=frd_reg", this.ipAddr);
            this.urledHandler = delegate (string v1,string v2)
            {
                HtmlDocument frameDocment = document.Window.Frames["paramIframe"].Document;
                System.Console.WriteLine(frameDocment.Body.OuterHtml);
            };
            document.InvokeScript("queryDrvItem");




            

            
        }



        /// <summary>
        /// 执行页面跳转
        /// </summary>
        /// <param name="browser">浏览器</param>
        /// <param name="url">地址</param>
        /// <returns>浏览器</returns>
        private WebBrowser Execute(WebBrowser browser, string url)
        {
            bool loadFinished = false;
            int num = 50;
            try
            {

                

                browser.DocumentCompleted += delegate (object a, WebBrowserDocumentCompletedEventArgs b)
                {
                    SimpleConsole.WriteInfo("已导航到的Url->" + b.Url,this);
                    //string outerHtml = browser.Document.Body.OuterHtml;
                    //SimpleConsole.WriteInfo(outerHtml,this);
                    loadFinished = true;
                };
                SimpleConsole.WriteInfo("即将要导航的Url->" + url,this);
                browser.Navigate(new Uri(url), false);
                while (!loadFinished && num > 0)
                {
                    Thread.Sleep(200);
                    SimpleConsole.WriteInfo("第[" + (50 - num) + "]尝试等待",this);
                    Application.DoEvents();
                    num--;
                }
                string title = browser.Document.Title;
                if ("导航已取消" == title)
                {
                    throw new Exception("无法连接远程服务");
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return browser;
        }


        private void AddCookie(CookieCollection tempCookieColl, string tempStrCookies, string domain)
        {
            System.Console.WriteLine("============设置Cookies开始===========");
            string[] array = tempStrCookies.Split(new char[]
            {
                ';'
            });
            foreach (string text in array)
            {
                string text2 = string.Empty;
                string text3 = string.Empty;
                Cookie cookie = new Cookie();
                cookie.Expires = DateTime.Now.Add(new TimeSpan(1000, 0, 0));
                string text4 = text.Trim();
                if (!string.IsNullOrEmpty(text4))
                {
                    if (text4.Contains("="))
                    {
                        string[] array3 = text.Split(new char[]
                        {
                            '='
                        });
                        if (array3.Length > 1)
                        {
                            text2 = array3[0].Trim();
                            text3 = array3[1].Trim();
                        }
                        else if (array3.Length == 1)
                        {
                            if (array3[0] == "dyjxh")
                            {
                                text2 = array3[0].Trim();
                                text3 = PRINTER_SN;
                            }
                            else
                            {
                                text2 = array3[0].Trim();
                                text3 = string.Empty;
                            }
                        }
                    }
                    else if (text4 == "dyjxh")
                    {
                        text2 = text4;
                        text3 = PRINTER_SN;
                    }
                    else
                    {
                        text2 = text4;
                        text3 = string.Empty;
                    }
                    cookie.Name = text2;
                    cookie.Value = text3;
                    cookie.Path = "/";
                    cookie.Domain = domain;
                    tempCookieColl.Add(cookie);
                    PrintUtil.InternetSetCookie(string.Format("http://{0}/trffweb/ywsl.do?method=frd_reg", this.ipAddr), text2, text3.ToString() + ";expires = Sun,18-Jul-2021 00:00:00 GMT");
                    System.Console.WriteLine("============设置Cookies结束===========");
                }
            }
        }

        private void GetValidCode(string html)
        {
            string pattern = "<input\\s*type='hidden'\\s*name='abcd(?<value1>.*?)'\\s*value='(?<value2>.*?)'/>";
            Regex regex = new Regex(pattern, RegexOptions.IgnoreCase | RegexOptions.Multiline);
            MatchCollection matchCollection = regex.Matches(html);
            foreach (object obj in matchCollection)
            {
                Match match = (Match)obj;
                this.validChar[0] = "abcd" + match.Groups["value1"].Value.ToString();
                this.validChar[1] = match.Groups["value2"].Value.ToString();
            }
        }

      


    }


    
}
